package net.minecraft.util;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map.Entry;

public interface IChatComponent extends Iterable<IChatComponent> {
	IChatComponent setChatStyle(ChatStyle style);

	ChatStyle getChatStyle();

	/**
	 * Appends the given text to the end of this component.
	 */
	IChatComponent appendText(String text);

	/**
	 * Appends the given component to the end of this one.
	 */
	IChatComponent appendSibling(IChatComponent component);

	/**
	 * Gets the text of this component, without any special formatting codes added,
	 * for chat. TODO: why is this two different methods?
	 */
	String getUnformattedTextForChat();

	/**
	 * Get the text of this component, <em>and all child components</em>, with all
	 * special formatting codes removed.
	 */
	String getUnformattedText();

	/**
	 * Gets the text of this component, with formatting codes added for rendering.
	 */
	String getFormattedText();

	List<IChatComponent> getSiblings();

	/**
	 * Creates a copy of this component. Almost a deep copy, except the style is
	 * shallow-copied.
	 */
	IChatComponent createCopy();

	public static class Serializer implements JsonDeserializer<IChatComponent>, JsonSerializer<IChatComponent> {
		private static final Gson GSON;

		public IChatComponent deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_,
				JsonDeserializationContext p_deserialize_3_) throws JsonParseException {
			if (p_deserialize_1_.isJsonPrimitive()) {
				return new ChatComponentText(p_deserialize_1_.getAsString());
			} else if (!p_deserialize_1_.isJsonObject()) {
				if (p_deserialize_1_.isJsonArray()) {
					JsonArray jsonarray1 = p_deserialize_1_.getAsJsonArray();
					IChatComponent ichatcomponent1 = null;

					for (JsonElement jsonelement : jsonarray1) {
						IChatComponent ichatcomponent2 = this.deserialize(jsonelement, jsonelement.getClass(),
								p_deserialize_3_);

						if (ichatcomponent1 == null) {
							ichatcomponent1 = ichatcomponent2;
						} else {
							ichatcomponent1.appendSibling(ichatcomponent2);
						}
					}

					return ichatcomponent1;
				} else {
					throw new JsonParseException(
							"Don\'t know how to turn " + p_deserialize_1_.toString() + " into a Component");
				}
			} else {
				JsonObject jsonobject = p_deserialize_1_.getAsJsonObject();
				IChatComponent ichatcomponent;

				if (jsonobject.has("text")) {
					ichatcomponent = new ChatComponentText(jsonobject.get("text").getAsString());
				} else if (jsonobject.has("translate")) {
					String s = jsonobject.get("translate").getAsString();

					if (jsonobject.has("with")) {
						JsonArray jsonarray = jsonobject.getAsJsonArray("with");
						Object[] aobject = new Object[jsonarray.size()];

						for (int i = 0; i < aobject.length; ++i) {
							aobject[i] = this.deserialize(jsonarray.get(i), p_deserialize_2_, p_deserialize_3_);

							if (aobject[i] instanceof ChatComponentText) {
								ChatComponentText chatcomponenttext = (ChatComponentText) aobject[i];

								if (chatcomponenttext.getChatStyle().isEmpty()
										&& chatcomponenttext.getSiblings().isEmpty()) {
									aobject[i] = chatcomponenttext.getChatComponentText_TextValue();
								}
							}
						}

						ichatcomponent = new ChatComponentTranslation(s, aobject);
					} else {
						ichatcomponent = new ChatComponentTranslation(s, new Object[0]);
					}
				} else if (jsonobject.has("score")) {
					JsonObject jsonobject1 = jsonobject.getAsJsonObject("score");

					if (!jsonobject1.has("name") || !jsonobject1.has("objective")) {
						throw new JsonParseException("A score component needs a least a name and an objective");
					}

					ichatcomponent = new ChatComponentScore(JsonUtils.getString(jsonobject1, "name"),
							JsonUtils.getString(jsonobject1, "objective"));

					if (jsonobject1.has("value")) {
						((ChatComponentScore) ichatcomponent).setValue(JsonUtils.getString(jsonobject1, "value"));
					}
				} else {
					if (!jsonobject.has("selector")) {
						throw new JsonParseException(
								"Don\'t know how to turn " + p_deserialize_1_.toString() + " into a Component");
					}

					ichatcomponent = new ChatComponentSelector(JsonUtils.getString(jsonobject, "selector"));
				}

				if (jsonobject.has("extra")) {
					JsonArray jsonarray2 = jsonobject.getAsJsonArray("extra");

					if (jsonarray2.size() <= 0) {
						throw new JsonParseException("Unexpected empty array of components");
					}

					for (int j = 0; j < jsonarray2.size(); ++j) {
						ichatcomponent
								.appendSibling(this.deserialize(jsonarray2.get(j), p_deserialize_2_, p_deserialize_3_));
					}
				}

				ichatcomponent
						.setChatStyle((ChatStyle) p_deserialize_3_.deserialize(p_deserialize_1_, ChatStyle.class));
				return ichatcomponent;
			}
		}

		private void serializeChatStyle(ChatStyle style, JsonObject object, JsonSerializationContext ctx) {
			JsonElement jsonelement = ctx.serialize(style);

			if (jsonelement.isJsonObject()) {
				JsonObject jsonobject = (JsonObject) jsonelement;

				for (Entry<String, JsonElement> entry : jsonobject.entrySet()) {
					object.add((String) entry.getKey(), (JsonElement) entry.getValue());
				}
			}
		}

		public JsonElement serialize(IChatComponent p_serialize_1_, Type p_serialize_2_,
				JsonSerializationContext p_serialize_3_) {
			if (p_serialize_1_ instanceof ChatComponentText && p_serialize_1_.getChatStyle().isEmpty()
					&& p_serialize_1_.getSiblings().isEmpty()) {
				return new JsonPrimitive(((ChatComponentText) p_serialize_1_).getChatComponentText_TextValue());
			} else {
				JsonObject jsonobject = new JsonObject();

				if (!p_serialize_1_.getChatStyle().isEmpty()) {
					this.serializeChatStyle(p_serialize_1_.getChatStyle(), jsonobject, p_serialize_3_);
				}

				if (!p_serialize_1_.getSiblings().isEmpty()) {
					JsonArray jsonarray = new JsonArray();

					for (IChatComponent ichatcomponent : p_serialize_1_.getSiblings()) {
						jsonarray.add(this.serialize((IChatComponent) ichatcomponent, ichatcomponent.getClass(),
								p_serialize_3_));
					}

					jsonobject.add("extra", jsonarray);
				}

				if (p_serialize_1_ instanceof ChatComponentText) {
					jsonobject.addProperty("text",
							((ChatComponentText) p_serialize_1_).getChatComponentText_TextValue());
				} else if (p_serialize_1_ instanceof ChatComponentTranslation) {
					ChatComponentTranslation chatcomponenttranslation = (ChatComponentTranslation) p_serialize_1_;
					jsonobject.addProperty("translate", chatcomponenttranslation.getKey());

					if (chatcomponenttranslation.getFormatArgs() != null
							&& chatcomponenttranslation.getFormatArgs().length > 0) {
						JsonArray jsonarray1 = new JsonArray();

						for (Object object : chatcomponenttranslation.getFormatArgs()) {
							if (object instanceof IChatComponent) {
								jsonarray1.add(this.serialize((IChatComponent) ((IChatComponent) object),
										object.getClass(), p_serialize_3_));
							} else {
								jsonarray1.add(new JsonPrimitive(String.valueOf(object)));
							}
						}

						jsonobject.add("with", jsonarray1);
					}
				} else if (p_serialize_1_ instanceof ChatComponentScore) {
					ChatComponentScore chatcomponentscore = (ChatComponentScore) p_serialize_1_;
					JsonObject jsonobject1 = new JsonObject();
					jsonobject1.addProperty("name", chatcomponentscore.getName());
					jsonobject1.addProperty("objective", chatcomponentscore.getObjective());
					jsonobject1.addProperty("value", chatcomponentscore.getUnformattedTextForChat());
					jsonobject.add("score", jsonobject1);
				} else {
					if (!(p_serialize_1_ instanceof ChatComponentSelector)) {
						throw new IllegalArgumentException(
								"Don\'t know how to serialize " + p_serialize_1_ + " as a Component");
					}

					ChatComponentSelector chatcomponentselector = (ChatComponentSelector) p_serialize_1_;
					jsonobject.addProperty("selector", chatcomponentselector.getSelector());
				}

				return jsonobject;
			}
		}

		public static String componentToJson(IChatComponent component) {
			return GSON.toJson((Object) component);
		}

		public static IChatComponent jsonToComponent(String json) {
			return (IChatComponent) GSON.fromJson(json, IChatComponent.class);
		}

		static {
			GsonBuilder gsonbuilder = new GsonBuilder();
			gsonbuilder.registerTypeHierarchyAdapter(IChatComponent.class, new IChatComponent.Serializer());
			gsonbuilder.registerTypeHierarchyAdapter(ChatStyle.class, new ChatStyle.Serializer());
			gsonbuilder.registerTypeAdapterFactory(new EnumTypeAdapterFactory());
			GSON = gsonbuilder.create();
		}
	}
}
